package org.ssp.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.ssp.pojo.Travel;
import org.ssp.pojo.BaseMessage;
import org.ssp.pojo.ImageMessage;
import org.ssp.pojo.MusicMessage;
import org.ssp.pojo.NewsMessage;
import org.ssp.pojo.TextMessage;
import org.ssp.pojo.VideoMessage;
import org.ssp.pojo.VoiceMessage;
import org.ssp.service.CoreService;

import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

public class MessageUtil {
	//final关键字表示不可修改
	//请求消息类型	
	public static final String REQ_MESSAGE_TYPE_TEXT="text";
	public static final String REQ_MESSAGE_TYPE_IMAGE="image";
	public static final String REQ_MESSAGE_TYPE_VOICE="voice";
	public static final String REQ_MESSAGE_TYPE_VIDEO="shortvideo";
	public static final String REQ_MESSAGE_TYPE_LOCATION="location";
	public static final String REQ_MESSAGE_TYPE_LINK="link";
	
	//响应消息类型
	
	public static final String RES_MESSAGE_TYPE_TEXT="text";
	public static final String RES_MESSAGE_TYPE_IMAGE="image";
	public static final String RES_MESSAGE_TYPE_VOICE="voice";
	public static final String RES_MESSAGE_TYPE_VIDEO="video";
	public static final String RES_MESSAGE_TYPE_MUSIC="music";
	public static final String RES_MESSAGE_TYPE_NEWS="news";
	public static final String RES_MESSAGE_TYPE_TRANSFER="transfer_customer_service";

	
	//事件消息类型
	public static final String REQ_MESSAGE_TYPE_EVENT="event";
	
	
	public static final String EVENT_TYPE_SUBSCRIBE="subscribe";
	public static final String EVENT_TYPE_UNSUBSCRIBE="unsubscribe";
	public static final String EVENT_TYPE_CLICK="CLICK";
	
	
	/**
	 * 
	 * 明文模式的xml解析
	 * @param request
	 * @return
	 * @throws Exception
	 * @throws IOException
	 */
	public static HashMap<String,String> parseXML(HttpServletRequest request) throws Exception, IOException{
		//collection
		HashMap<String,String> map=new HashMap<String,String>();
		
		//通过io获得Document
		SAXReader reader=new SAXReader();
		//从request得到输入流
		Document doc1=reader.read(request.getInputStream());
		//获取文档根节点
		Element root=doc1.getRootElement();
		recursiveParseXML(root,map);
		return map;
	}
	
	/**
	 * 
	 *加密模式的xml解析
	 * @param request
	 * @return
	 */
	public static HashMap<String,String> parseXMLCrypt(HttpServletRequest request){
		HashMap<String,String> map=new HashMap<String,String>();

		//io流
		//1，从inputstream读取加密的xml文本
		StringBuffer buffer=null;
		try {
			InputStream is=request.getInputStream();
			BufferedReader br=new BufferedReader(new InputStreamReader(is));
			//表示每次读取的内容
			String line=null;
			//我们最终读取的内容
		    buffer=new StringBuffer();
			
			while((line=br.readLine())!=null){
				buffer.append(line);
			}
			br.close();
			is.close();
			
			
		} catch (IOException e) {
		}
		
		//2.调用示例代码，将加密的xml解析为明文的xml
		String msgSignature=request.getParameter("msg_signature");
		String timeStamp=request.getParameter("timestamp");
		String nonce=request.getParameter("nonce"); 
		WXBizMsgCrypt wxCrypt=MessageUtil.getWxEncrypt();
		String reqXML=null;
		try {
			reqXML=wxCrypt.decryptMsg(msgSignature, timeStamp, nonce,buffer.toString());
		} catch (AesException e) {
			e.printStackTrace();
		}
	
		//3.解析明文xml，获取请求参数，从字符串解析
		try {
			Document doc=DocumentHelper.parseText(reqXML);
			Element root=doc.getRootElement();
			recursiveParseXML(root,map);

		} catch (DocumentException e) {
			e.printStackTrace();
		}
		
		return map;
	}
	
	/**
	 * 
	 * 微信公众平台提供的加解密示例代码
	 * @return
	 */
	public static WXBizMsgCrypt getWxEncrypt(){
		WXBizMsgCrypt pc=null;
		try {
			//encodingAesKey根据前台的设置来更改
			pc = new WXBizMsgCrypt(SignUtil.token,"xlLWz8FzebvuOC0LKDJjd202R9KSoMqPskqjGeHuqdv", CoreService.AppID);
		} catch (AesException e) {
			e.printStackTrace();
		}
		return pc;
		
	}


	
	public static void recursiveParseXML(Element root,HashMap<String,String> map){
		//得到根节点的所有子节点列表
		List<Element>elementList=root.elements();
		if(elementList.size()==0){
			map.put(root.getName(),root.getTextTrim());
			
		}else{
			for(Element e:elementList){
				recursiveParseXML(e,map);
			}
		}
		
	}
	
	//响应消息对象转换成XML,使用接口、继承、多态重构

	public static String messageToXML(TextMessage textMessage){
		xstream.alias("xml", TextMessage.class);
		return xstream.toXML(textMessage);
		
	}
	public static String messageToXML(ImageMessage imageMessage){
		xstream.alias("xml", ImageMessage.class);
		return xstream.toXML(imageMessage);
		
	}
	public static String messageToXML(VoiceMessage voiceMessage){
		xstream.alias("xml", VoiceMessage.class);
		return xstream.toXML(voiceMessage);
		
	}
	public static String messageToXML(VideoMessage videoMessage){
		xstream.alias("xml", VideoMessage.class);
		return xstream.toXML(videoMessage);
		
	}
	public static String messageToXML(MusicMessage musicMessage){
		xstream.alias("xml", MusicMessage.class);
		return xstream.toXML(musicMessage);
		
	}
	public static String messageToXML(NewsMessage newsMessage){
		xstream.alias("xml", NewsMessage.class);
		xstream.alias("item",Travel.class);
		return xstream.toXML(newsMessage);
		
	}
	public static String messageToXML(BaseMessage message){
		xstream.alias("xml", BaseMessage.class);
		return xstream.toXML(message);
		
	}
	//XStream扩展，使XML元素被CDATA包裹
	public static XStream xstream=new XStream(new XppDriver(){
		public HierarchicalStreamWriter createWriter(Writer out){
			return new PrettyPrintWriter(out){
				boolean cdata=true;
				public void startNode(String name,Class clazz){
					super.startNode(name,clazz);
				}
				protected void writeText(QuickWriter writer,String text){
					if(cdata){
						writer.write("<![CDATA[");
						writer.write(text);
						writer.write("]]>");
					}else{
						writer.write(text);
						
					}
				}
			};
			
		}
	});
	
	
	//返回字节长度
	public static int getByteSize(String content){
		int size=0;
		try {
			if(content!=null)
				size=content.getBytes("utf-8").length;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
			
		return size;
		
	}
	public static String emoji(int hexEmoji){
		return String.valueOf(Character.toChars(hexEmoji));
		
	}
	

}
